Skip to content

feat(aarch64): add GDB debugging for Windows ARM64 WHP - #1907

Open
cshung wants to merge 3 commits into
hyperlight-dev:mainfrom
cshung:cshung/whp-aarch64-gdb
Open

cshung wants to merge 3 commits into
hyperlight-dev:mainfrom
cshung:cshung/whp-aarch64-gdb

Conversation

@cshung

@cshung cshung commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds GDB stub support for guests running on the ARM64 WHP backend.

Changes

Debug core

  • Split the x86_64 debug code out of hyperlight_vm/x86_64.rs into a shared hyperlight_vm/debug.rs.
  • Rename gdb/x86_64_target.rs to gdb/target.rs and add per-architecture register handling in gdb/arch/.
  • Give DebuggableVm default methods so backends without hardware breakpoints or single step report Unsupported.

ARM64 WHP

  • Implement DebuggableVm for the aarch64 WHP VM, using the batched register helpers.
  • Flush the host instruction cache after guest memory writes so software breakpoints take effect.

Docs

  • Document ARM64 debugging in docs/how-to-debug-a-hyperlight-guest.md and CHANGELOG.md.

Verification

On Windows ARM64 (WHP):

  • just build, just clippy, just guests, just test and just fmt-check pass.

@cshung cshung added the kind/enhancement For PRs adding features, improving functionality, docs, tests, etc. label Oct 8, 2026
@hyperlight-gh-bot

This comment has been minimized.

@cshung
cshung marked this pull request as ready for review October 8, 2026 19:33
Copilot AI balanced review requested due to automatic review settings October 8, 2026 19:33

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Breakpoint state can survive crash or cancellation recovery, and the hidden cache-sync mapping conflicts with the public mapping contract.

4 open findings
What changed in this PR

Adds Windows ARM64 WHP guest debugging and generalizes the GDB implementation across architectures.

Changes:

  • Adds ARM64 registers, software breakpoints, stepping, and cache synchronization.
  • Extracts shared debugger logic from x86_64 code.
  • Updates tests, documentation, and platform configuration.
File Description
CHANGELOG.md Records ARM64 GDB support.
docs/​how-to-debug-a-hyperlight-guest.md Documents architecture-specific capabilities.
src/​hyperlight_host/​build.rs Enables GDB on Windows ARM64.
src/​hyperlight_host/​examples/​guest-debugging/​main.rs Adds ARM64 debugging tests.
src/​hyperlight_host/​src/​hypervisor/​gdb/​arch.rs Dispatches architecture-specific logic.
src/​hyperlight_host/​src/​hypervisor/​gdb/​arch/​aarch64.rs Implements ARM64 breakpoint and step decoding.
src/​hyperlight_host/​src/​hypervisor/​gdb/​arch/​x86_64.rs Houses extracted x86_64 logic.
src/​hyperlight_host/​src/​hypervisor/​gdb/​event_loop.rs Maps ARM64 stop reasons.
src/​hyperlight_host/​src/​hypervisor/​gdb/​mod.rs Extends shared debugging interfaces.
src/​hyperlight_host/​src/​hypervisor/​gdb/​target.rs Adds architecture-specific GDB registers.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​aarch64.rs Connects GDB to ARM64 VMs.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​debug.rs Centralizes breakpoint and stepping state.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​mod.rs Handles ARM64 debug exits.
src/​hyperlight_host/​src/​hypervisor/​hyperlight_vm/​x86_64.rs Removes extracted debugger logic.
src/​hyperlight_host/​src/​hypervisor/​virtual_machine/​mod.rs Extends VM exits and errors.
src/​hyperlight_host/​src/​hypervisor/​virtual_machine/​whp/​aarch64.rs Implements WHP debugging and cache synchronization.
src/​hyperlight_host/​src/​sandbox/​initialized.rs Guards snapshots with active breakpoints.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@cshung
cshung force-pushed the cshung/whp-aarch64-gdb branch from 8c0c245 to 39ea4cb Compare October 9, 2026 16:54
@hyperlight-gh-bot

This comment has been minimized.

@syntactically

Copy link
Copy Markdown
Member

@cshung I guess you are using software breakpoints here because WHPX aarch64 does not yet support setting MDCR_EL2.TDE. I think this is very divergent from the other implementations and especially the emulation of software step looks very fragile in its current state.

I wonder if we can make things a little bit more congruent with the other implementations by using the same hardware debug approach as other targets, but on WHP set MDSCR_EL1.KDE and have little assembly stubs catch this case and make hvcs (or, even make an hvc on every exception entry, when in gdb mode)? Admittedly this will not work very well if VBAR_EL1 or virtual memory configuration for the exception handlers are messed up, but in that case I think given the current guest architecture it is extremely unlikely that guest code would continue to execute and produce any useful results.

@cshung
cshung force-pushed the cshung/whp-aarch64-gdb branch from 7238539 to 6c35092 Compare October 19, 2026 14:56
@hyperlight-gh-bot

This comment has been minimized.

@hyperlight-gh-bot

This comment has been minimized.

@hyperlight-gh-bot

This comment has been minimized.

@cshung
cshung force-pushed the cshung/whp-aarch64-gdb branch from dd86b49 to 698b851 Compare October 20, 2026 17:59
@hyperlight-gh-bot

This comment has been minimized.

@cshung
cshung force-pushed the cshung/whp-aarch64-gdb branch from 698b851 to 3e3983f Compare October 26, 2026 16:30
@hyperlight-gh-bot

This comment has been minimized.

cshung and others added 3 commits October 30, 2026 09:30
Adds GDB stub support for guests running on the ARM64 WHP backend.

* Split the x86_64 debug code out of `hyperlight_vm/x86_64.rs` into a shared `hyperlight_vm/debug.rs`.
* Rename `gdb/x86_64_target.rs` to `gdb/target.rs` and add per-architecture register handling in `gdb/arch/`.
* Give `DebuggableVm` default methods so backends without hardware breakpoints or single step report `Unsupported`.

* Implement `DebuggableVm` for the aarch64 WHP VM, using the batched register helpers.
* Flush the host instruction cache after guest memory writes so software breakpoints take effect.

* Document ARM64 debugging in `docs/how-to-debug-a-hyperlight-guest.md` and `CHANGELOG.md`.

On Windows ARM64 (WHP):
* `just build`, `just clippy`, `just guests`, `just test` and `just fmt-check` pass.

---------

Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
## Changes

* Run the full disable path when the debugger detaches after a crash, so software breakpoints and pending steps are cleaned up.
* Cancel pending software steps for any cancellation source, not only debugger interrupts.
* Reject `map_region` requests that overlap the hidden cache sync page at GPA 0x1000, and add a test.
* Restore the `≡` and `×` characters in `hyperlight_vm/x86_64.rs` comments.

## Verification

On Windows ARM64 (WHP):
* `just clippy`, `just fmt-check` and the `hypervisor::` and `map_region` lib tests with the `gdb` feature pass.

---------

Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Guest synchronous exception vectors forward debug stops through HVC. Hardware single-step supports branches, returns, and self-loops. Two hardware breakpoint slots and BRK software breakpoints are available.

Interrupted register context and breakpoint configuration survive cache synchronization and vCPU reset. Asynchronous vectors retain their normal exception paths.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: cshung <3410332+cshung@users.noreply.github.com>
@cshung
cshung force-pushed the cshung/whp-aarch64-gdb branch from 3e3983f to bed283f Compare October 30, 2026 16:47
@hyperlight-gh-bot

Copy link
Copy Markdown

Benchmark Results

Measured commit: bed283fb3067
Baseline commit: a4563dbd585d

kvm / amd (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

decode_vec_bytes_copy encode_control
375.67 µs (➖ 1.01x slower)
byte_chunks 761.37 ns (➖ 1.01x faster)
vec_bytes 588.13 ns (➖ 1.01x slower)

payload_allocation

slot_pool_segmented
65536 141.35 ns (➖ 1.00x faster)
262144 521.26 ns (➖ 1.10x faster)

sandboxes

create_initialized_and_drop
medium 80.21 ms (➖ 1.00x faster)

slot_pool

alloc_dealloc_4096 alloc_dealloc_128 alloc_dealloc_1500
7.68 ns (➖ 1.00x faster) 7.69 ns (➖ 1.01x faster) 7.69 ns (➖ 1.00x faster)

snapshot_files

load_snapshot_unverified
small 92.03 µs (➖ 1.00x faster)

virtq_readonly

slot_pool_segmented slot_pool_segmented_fragmented
65536 1.94 µs (➖ 1.07x faster) 2.05 µs (➖ 1.07x slower)
262144 7.11 µs (➖ 1.01x faster) 7.23 µs (➖ 1.02x faster)

virtq_readwrite

slot_pool_segmented slot_pool_segmented_fragmented
8192 1.02 µs (➖ 1.02x slower) 1.01 µs (➖ 1.05x faster)
65536 6.32 µs (➖ 1.04x faster) 6.11 µs (➖ 1.04x faster)
262144 27.13 µs (➖ 1.02x faster)
kvm / intel (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

decode_vec_bytes_copy encode_control
754.29 µs (➖ 1.00x slower)
byte_chunks 827.99 ns (➖ 1.04x slower)
vec_bytes 581.89 ns (➖ 1.04x faster)

payload_allocation

slot_pool_segmented
65536 202.97 ns (➖ 1.00x slower)
262144 584.81 ns (➖ 1.01x faster)

sandboxes

create_initialized_and_drop
medium 84.24 ms (➖ 1.02x slower)

slot_pool

alloc_dealloc_4096 alloc_dealloc_128 alloc_dealloc_1500
8.01 ns (➖ 1.01x faster) 8.03 ns (➖ 1.01x faster) 8.13 ns (➖ 1.00x faster)

snapshot_files

load_snapshot_unverified
small 51.22 µs (➖ 1.02x faster)

virtq_readonly

slot_pool_segmented slot_pool_segmented_fragmented
65536 2.55 µs (➖ 1.00x slower) 2.53 µs (➖ 1.01x faster)
262144 8.94 µs (➖ 1.01x faster) 8.85 µs (➖ 1.01x faster)

virtq_readwrite

slot_pool_segmented slot_pool_segmented_fragmented
8192 857.13 ns (➖ 1.01x slower) 921.64 ns (➖ 1.06x slower)
65536 8.45 µs (➖ 1.00x faster) 8.38 µs (➖ 1.01x faster)
262144 34.90 µs (➖ 1.00x slower)
mshv3 / amd (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

decode_vec_bytes_copy encode_control
299.20 µs (➖ 1.12x slower)
byte_chunks 950.55 ns (➖ 1.00x faster)
vec_bytes 738.55 ns (➖ 1.01x slower)

payload_allocation

slot_pool_segmented
65536 196.62 ns (➖ 1.02x slower)
262144 731.51 ns (➖ 1.00x slower)

sandboxes

create_initialized_and_drop
medium 60.36 ms (➖ 1.05x slower)

slot_pool

alloc_dealloc_4096 alloc_dealloc_128 alloc_dealloc_1500
9.53 ns (➖ 1.05x faster) 9.51 ns (➖ 1.01x faster) 15.61 ns (➖ 1.52x slower)

snapshot_files

load_snapshot_unverified
small 86.09 µs (➖ 1.00x faster)

virtq_readonly

slot_pool_segmented slot_pool_segmented_fragmented
65536 2.63 µs (➖ 1.18x slower) 2.45 µs (➖ 1.01x faster)
262144 10.07 µs (➖ 1.05x slower) 11.71 µs (➖ 1.00x slower)

virtq_readwrite

slot_pool_segmented slot_pool_segmented_fragmented
8192 1.34 µs (➖ 1.14x slower) 1.22 µs (➖ 1.01x faster)
65536 8.35 µs (➖ 1.14x faster) 8.44 µs (➖ 1.14x faster)
262144 35.96 µs (➖ 1.07x faster)
mshv3 / intel (Linux) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

decode_vec_bytes_copy encode_control
698.71 µs (➖ 1.06x slower)
byte_chunks 898.79 ns (➖ 1.01x faster)
vec_bytes 661.65 ns (➖ 1.01x slower)

payload_allocation

slot_pool_segmented
65536 264.19 ns (➖ 1.24x faster)
262144 661.12 ns (➖ 1.02x faster)

sandboxes

create_initialized_and_drop
medium 62.00 ms (➖ 1.06x faster)

slot_pool

alloc_dealloc_4096 alloc_dealloc_128 alloc_dealloc_1500
8.67 ns (➖ 1.00x faster) 8.72 ns (➖ 1.01x faster) 8.78 ns (➖ 1.01x slower)

snapshot_files

load_snapshot_unverified
small 43.74 µs (➖ 1.00x slower)

virtq_readonly

slot_pool_segmented slot_pool_segmented_fragmented
65536 2.29 µs (➖ 1.00x slower) 2.26 µs (➖ 1.01x faster)
262144 7.94 µs (➖ 1.00x faster) 7.94 µs (➖ 1.00x slower)

virtq_readwrite

slot_pool_segmented slot_pool_segmented_fragmented
8192 915.64 ns (➖ 1.00x slower) 906.11 ns (➖ 1.00x slower)
65536 7.42 µs (➖ 1.00x faster) 7.45 µs (➖ 1.01x faster)
262144 37.99 µs (➖ 1.02x faster)
hyperv-ws2025 / amd (Windows) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

decode_vec_bytes_copy encode_control
2.01 ms (➖ 1.03x slower)
byte_chunks 1.17 µs (➖ 1.06x faster)
vec_bytes 776.56 ns (➖ 1.02x faster)

payload_allocation

slot_pool_segmented
65536 229.66 ns (➖ 1.00x slower)
262144 796.00 ns (➖ 1.02x slower)

sandboxes

create_initialized_and_drop
medium 79.01 ms (➖ 1.00x slower)

slot_pool

alloc_dealloc_4096 alloc_dealloc_128 alloc_dealloc_1500
10.49 ns (➖ 1.05x slower) 9.97 ns (➖ 1.00x faster) 10.85 ns (➖ 1.10x slower)

snapshot_files

load_snapshot_unverified
small 752.37 µs (➖ 1.10x slower)

virtq_readonly

slot_pool_segmented slot_pool_segmented_fragmented
65536 2.36 µs (➖ 1.01x slower) 2.31 µs (➖ 1.00x faster)
262144 9.06 µs (➖ 1.03x faster) 8.92 µs (➖ 1.03x faster)

virtq_readwrite

slot_pool_segmented slot_pool_segmented_fragmented
8192 1.27 µs (➖ 1.04x faster) 1.27 µs (➖ 1.01x faster)
65536 9.27 µs (➖ 1.00x faster) 8.96 µs (➖ 1.04x faster)
262144 38.33 µs (➖ 1.17x faster)
hyperv-ws2025 / intel (Windows) (➖ stable)

No benchmark improved or regressed.

Benchmark Results

function_call_codec

decode_vec_bytes_copy encode_control
3.06 ms (➖ 1.01x slower)
byte_chunks 1.19 µs (➖ 1.01x slower)
vec_bytes 780.07 ns (➖ 1.00x slower)

payload_allocation

slot_pool_segmented
65536 210.37 ns (➖ 1.02x faster)
262144 738.01 ns (➖ 1.00x faster)

sandboxes

create_initialized_and_drop
medium 106.42 ms (➖ 1.05x faster)

slot_pool

alloc_dealloc_4096 alloc_dealloc_128 alloc_dealloc_1500
10.12 ns (➖ 1.07x faster) 9.73 ns (➖ 1.01x faster) 9.68 ns (➖ 1.01x slower)

snapshot_files

load_snapshot_unverified
small 540.87 µs (➖ 1.19x faster)

virtq_readonly

slot_pool_segmented slot_pool_segmented_fragmented
65536 2.50 µs (➖ 1.07x slower) 2.35 µs (➖ 1.03x slower)
262144 7.55 µs (➖ 1.01x faster) 7.69 µs (➖ 1.02x slower)

virtq_readwrite

slot_pool_segmented slot_pool_segmented_fragmented
8192 1.21 µs (➖ 1.13x slower) 1.30 µs (➖ 1.21x slower)
65536 8.93 µs (➖ 1.06x slower) 8.93 µs (➖ 1.07x slower)
262144 47.66 µs (➖ 1.05x faster)

Reported by cargo ci bench-report --candidate run:41093016637 --config-file bench_report.toml.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/enhancement For PRs adding features, improving functionality, docs, tests, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants